package short_semester.questionnaire_planet.service.editService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import short_semester.questionnaire_planet.dao.*;
import short_semester.questionnaire_planet.pojo.*;
import short_semester.questionnaire_planet.request.fillRequest.relation.RelationRequest;
import short_semester.questionnaire_planet.response.editResponse.MulRelationProperties;
import short_semester.questionnaire_planet.response.editResponse.RelationResponse;
import short_semester.questionnaire_planet.response.fillResponse.RelationLogicResponse;

import java.util.*;

@Service
public class RelationService {
    @Autowired
    QuestionnaireDao questionnaireDao;
    @Autowired
    RelationDao relationDao;
    @Autowired
    SingleChoiceQuestionDao singleChoiceQuestionDao;
    @Autowired
    MultiChoiceQuestionDao multiChoiceQuestionDao;
    @Autowired
    FillBlankQuestionDao fillBlankQuestionDao;
    @Autowired
    ScoreQuestionDao scoreQuestionDao;
    @Autowired
    QuestionSequenceDao sequenceDao;
    
    
    public RelationResponse getRelation(SingleChoiceQuestion question){
        RelationResponse response = new RelationResponse(question.getTitle());
        response.setLogic(question.getLogic());
        Object[] arr;
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            switch (relation.getRelationType()){
                case "radio":
                    SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(relation.getRelationId());
                    if(singleChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
                case "checkbox":
                    
                    MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(relation.getRelationId());
                    if(multiChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }
                    
                    String s = relation.getRelationType()+"@"+relation.getRelationId();
                    if(!response.getMap().containsKey(s))
                        response.getMap().put(s,new MulRelationProperties(relation.getIsChoose(),relation.getIsAll()));
                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
            }
        }
        return response;
    }

    public RelationResponse getRelation(MultiChoiceQuestion question){
        RelationResponse response = new RelationResponse(question.getTitle());
        response.setLogic(question.getLogic());
        Object[] arr;
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            switch (relation.getRelationType()){
                case "radio":
                    SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(relation.getRelationId());
                    if(singleChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
                case "checkbox":

                    MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(relation.getRelationId());
                    if(multiChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    String s = relation.getRelationType()+"@"+relation.getRelationId();
                    if(!response.getMap().containsKey(s))
                        response.getMap().put(s,new MulRelationProperties(relation.getIsChoose(),relation.getIsAll()));
                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
            }
        }
        return response;
    }

    public RelationResponse getRelation(FillBlankQuestion question){
        RelationResponse response = new RelationResponse(question.getTitle());
        response.setLogic(question.getLogic());
        Object[] arr;
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            switch (relation.getRelationType()){
                case "radio":
                    SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(relation.getRelationId());
                    if(singleChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
                case "checkbox":

                    MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(relation.getRelationId());
                    if(multiChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    String s = relation.getRelationType()+"@"+relation.getRelationId();
                    if(!response.getMap().containsKey(s))
                        response.getMap().put(s,new MulRelationProperties(relation.getIsChoose(),relation.getIsAll()));
                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
            }
        }
        return response;
    }

    public RelationResponse getRelation(ScoreQuestion question){
        RelationResponse response = new RelationResponse(question.getTitle());
        response.setLogic(question.getLogic());
        Object[] arr;
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            switch (relation.getRelationType()){
                case "radio":
                    SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(relation.getRelationId());
                    if(singleChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
                case "checkbox":

                    MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(relation.getRelationId());
                    if(multiChoiceQuestion.getSequence()>=question.getSequence()){
                        relationDao.delete(relation);
                        break;
                    }

                    String s = relation.getRelationType()+"@"+relation.getRelationId();
                    if(!response.getMap().containsKey(s))
                        response.getMap().put(s,new MulRelationProperties(relation.getIsChoose(),relation.getIsAll()));
                    arr = new Object[2];
                    arr[0] = relation.getRelationType()+"@"+relation.getRelationId();
                    arr[1] = relation.getOptionId();
                    response.getValue().add(arr);
                    break;
            }
        }
        return response;
    }
    
    public void submitRelation(RelationRequest request){
        
        Questionnaire questionnaire = questionnaireDao.getById(request.getQuestionnaireId());
        relationDao.deleteByQuestionIdAndType(request.getQuestionId(),request.getType());
        for (List<String> objects : request.getArr()) {
            String typeId = objects.get(0);
            String[] strings = typeId.split("@");
            Relation relation = null;
            switch (strings[0]){
                case "radio":
                    relation = new Relation(questionnaire,request.getQuestionId(),request.getType(),
                            Integer.parseInt(strings[1]),strings[0],Integer.parseInt(objects.get(1)));
                    relationDao.save(relation);
                    break;
                case "checkbox":
                    relation = new Relation(questionnaire,request.getQuestionId(),request.getType(),
                            Integer.parseInt(strings[1]),strings[0],Integer.parseInt(objects.get(1)));
                    relation.setIs(Boolean.parseBoolean(objects.get(2)),Boolean.parseBoolean(objects.get(3)));
                    relationDao.save(relation);
                    break;
            }
        }

        switch (request.getType()){
            case "radio":
                SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(request.getQuestionId());
                singleChoiceQuestion.setLogic(request.getLogic());
                singleChoiceQuestion.setRelationString(request.getRelationString());
                singleChoiceQuestionDao.save(singleChoiceQuestion);
                break;
            case "checkbox":
                MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(request.getQuestionId());
                multiChoiceQuestion.setLogic(request.getLogic());
                multiChoiceQuestion.setRelationString(request.getRelationString());
                multiChoiceQuestionDao.save(multiChoiceQuestion);
                break;
            case "completion":
                FillBlankQuestion fillBlankQuestion = fillBlankQuestionDao.getById(request.getQuestionId());
                fillBlankQuestion.setLogic(request.getLogic());
                fillBlankQuestion.setRelationString(request.getRelationString());
                fillBlankQuestionDao.save(fillBlankQuestion);
                break;
            case "score":
                ScoreQuestion scoreQuestion = scoreQuestionDao.getById(request.getQuestionId());
                scoreQuestion.setLogic(request.getLogic());
                scoreQuestion.setRelationString(request.getRelationString());
                scoreQuestionDao.save(scoreQuestion);
                break;
        }
    }
    
    public void delete(Integer questionnaireId){
        Questionnaire questionnaire = questionnaireDao.getById(questionnaireId);
        relationDao.deleteByQuestionnaire(questionnaire);
        for (SingleChoiceQuestion singleChoiceQuestion : singleChoiceQuestionDao.findByQuestionnaire(questionnaire)) {
            singleChoiceQuestion.setRelationString("");
            singleChoiceQuestionDao.save(singleChoiceQuestion);
        }
        for (MultiChoiceQuestion multiChoiceQuestion : multiChoiceQuestionDao.findByQuestionnaire(questionnaire)) {
            multiChoiceQuestion.setRelationString("");
            multiChoiceQuestionDao.save(multiChoiceQuestion);
        }
        for(FillBlankQuestion fillBlankQuestion:fillBlankQuestionDao.findByQuestionnaire(questionnaire)){
            fillBlankQuestion.setRelationString("");
            fillBlankQuestionDao.save(fillBlankQuestion);
        }
        for (ScoreQuestion scoreQuestion : scoreQuestionDao.findByQuestionnaire(questionnaire)) {
            scoreQuestion.setRelationString("");
            scoreQuestionDao.save(scoreQuestion);
        }
    }
    
    
    //填写问卷获取的关联关系
    public RelationLogicResponse getRelations(Questionnaire questionnaire){
        
        //判断
        if(!relationDao.existsByQuestionnaire(questionnaire)){
            return null;
        }
        RelationLogicResponse response = new RelationLogicResponse();
        Map<String, List<String>> caller = response.getCaller();
        Map<String, Map<String, Object>> relationMap = response.getRelationMap();
        for(QuestionSequence sequence: sequenceDao.findByQuestionnaireOrderBySequenceAsc(questionnaire)){
            
            LinkedList<String> list = new LinkedList<>();
            caller.put(sequence.typeId(), list);
            //作为提醒者
            for (Relation relation : relationDao.findByRelationIdAndRelationType(sequence.getQuestionId(), sequence.getType())) {
                //提醒type@questionId
                list.add(relation.getType()+"@"+relation.getQuestionId());
            }
            
            //作为被提醒者
            Map<String, Object> map = new HashMap();
            relationMap.put(sequence.typeId(),map);
            for (Relation relation : relationDao.findByQuestionIdAndType(sequence.getQuestionId(), sequence.getType())) {
//                map.put("logic",getQuestionLogicBySequence(sequence));
                //被relationType@relationId提醒
                String key = relation.getRelationType()+"@"+relation.getRelationId();
                if(map.containsKey(key)){
                    List<Object> list1 = (List<Object>) map.get(key);
                    list1.add(relation.getOptionId());
                }else{
                    List<Object> list1 = new LinkedList<>();
                    
                    if(relation.getRelationType().equals("checkbox")){
                        list1.add(relation.getIsChoose());
                        list1.add(relation.getIsAll());
                    }
                    list1.add(relation.getOptionId());
                    map.put(key,list1);
                }
            }
        }
        
        return response;
    }
    
    public String getQuestionLogicBySequence(QuestionSequence sequence){
        switch (sequence.getType()){
            case "radio":
                return singleChoiceQuestionDao.getById(sequence.getQuestionId()).getLogic();
            case "checkbox":
                return multiChoiceQuestionDao.getById(sequence.getQuestionId()).getLogic();
            case "completion":
                return fillBlankQuestionDao.getById(sequence.getQuestionId()).getLogic();
            case "score":
                return scoreQuestionDao.getById(sequence.getQuestionId()).getLogic();
        }
        return null;
    }
    
    public void relationString(Integer questionId,String type,String relationString){
        switch (type){
            case "radio":
                SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(questionId);
                singleChoiceQuestion.setRelationString(relationString);
                singleChoiceQuestionDao.save(singleChoiceQuestion);
                break;
            case "checkbox":
                MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(questionId);
                multiChoiceQuestion.setRelationString(relationString);
                multiChoiceQuestionDao.save(multiChoiceQuestion);
                break;
            case "completion":
                FillBlankQuestion fillBlankQuestion = fillBlankQuestionDao.getById(questionId);
                fillBlankQuestion.setRelationString(relationString);
                fillBlankQuestionDao.save(fillBlankQuestion);
            case "score":
                ScoreQuestion scoreQuestion = scoreQuestionDao.getById(questionId);
                scoreQuestion.setRelationString(relationString);
                scoreQuestionDao.save(scoreQuestion);
                break;
        }
    }

    //验证关联顺序
    public void relationVertify(Questionnaire questionnaire){
        Set<String> set = new HashSet<>();
        for (QuestionSequence sequence : sequenceDao.findByQuestionnaireOrderBySequenceAsc(questionnaire)) {
            switch (sequence.getType()){
                case "radio":
                    SingleChoiceQuestion singleChoiceQuestion = singleChoiceQuestionDao.getById(sequence.getQuestionId());
                    this.relationVertify(singleChoiceQuestion,set);
                    break;
                case "checkbox":
                    MultiChoiceQuestion multiChoiceQuestion = multiChoiceQuestionDao.getById(sequence.getQuestionId());
                    this.relationVertify(multiChoiceQuestion,set);
                    break;
                case "completion":
                    FillBlankQuestion fillBlankQuestion = fillBlankQuestionDao.getById(sequence.getQuestionId());
                    this.relationVertify(fillBlankQuestion,set);
                    break;
                case "score":
                    ScoreQuestion scoreQuestion = scoreQuestionDao.getById(sequence.getQuestionId());
                    this.relationVertify(scoreQuestion,set);
                    break;
            }
        }
    }
    
    public void relationVertify(SingleChoiceQuestion question,Set set){
        set.add(question.getType()+"@"+question.getId());
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            if(!set.contains(relation.getRelationType()+"@"+relation.getRelationId())){
                relationDao.delete(relation);
            }
        }
    }
    public void relationVertify(MultiChoiceQuestion question,Set set){
        set.add(question.getType()+"@"+question.getId());
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            if(!set.contains(relation.getRelationType()+"@"+relation.getRelationId())){
                relationDao.delete(relation);
            }
        }
    }
    public void relationVertify(FillBlankQuestion question, Set set){
        set.add(question.getType()+"@"+question.getId());
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            if(!set.contains(relation.getRelationType()+"@"+relation.getRelationId())){
                relationDao.delete(relation);
            }
        }
    }
    public void relationVertify(ScoreQuestion question,Set set){
        set.add(question.getType()+"@"+question.getId());
        for (Relation relation : relationDao.findByQuestionIdAndType(question.getId(), question.getType())) {
            if(!set.contains(relation.getRelationType()+"@"+relation.getRelationId())){
                relationDao.delete(relation);
            }
        }
    }
}
